package com.chen.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.chen.proxyProvider.UrlFormat;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import us.codecraft.webmagic.proxy.Proxy;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class IPProxyProvider {
    static Logger logger = LoggerFactory.getLogger("IPProxyProvider");
    static CloseableHttpClient httpClient = HttpClients.createDefault();
    static private RequestConfig reqConfig = null;

    static Lock lock = new ReentrantLock();

    static Properties properties = null;

    public static void setProperties(Properties properties) {
        IPProxyProvider.properties = properties;
    }

    static {
        reqConfig = RequestConfig.custom().setConnectionRequestTimeout(1000).setConnectTimeout(1000) // 设置连接超时时间
                .setSocketTimeout(10000) // 设置读取超时时间
                .setExpectContinueEnabled(false)
                .setCircularRedirectsAllowed(true) // 允许多次重定向
                .build();
    }

    /**
     * 从json格式中提取 proxys
     *
     * @param json
     * @return
     */
    static public List<Proxy> jsonToProxys(String json) {
        List<Proxy> proxies = new ArrayList<>();
        JSONObject jsonObject = com.alibaba.fastjson.JSON.parseObject(json);
        JSONArray data = jsonObject.getJSONArray("data");
        Iterator<Object> iterator = data.iterator();
        while (iterator.hasNext()) {
            JSONObject next = (JSONObject) iterator.next();
            String ip = next.getString("ip");
            int port = next.getInteger("port");
            proxies.add(new Proxy(ip, port));
        }
        if (proxies.size() == 0) {
            logger.warn(json);
            lock.lock();
            try {
                if (proxies.size() == 0) {
                    String ip = regex(json, "[0-9]+.[0-9]+.[0-9]+.[0-9]+");
                    String white = new UrlFormat(UrlFormat.ADDWHITELIST, properties).white(ip);
                    String resource = getResource(white);
                    System.out.println(resource);
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    String build = new UrlFormat(UrlFormat.ZMPROXY).setNum(1).setPort(1).setType(2).setTime(1).build();
                    return jsonToProxys(getResource(build));
                }
            } finally {
                lock.unlock();
            }
        }
        return proxies;
    }

    /**
     * 正则表达式获取第一个匹配的东东
     *
     * @param input
     * @param pattern
     * @return
     */
    static public String regex(String input, String pattern) {
        Pattern r = Pattern.compile(pattern);

        Matcher matcher = r.matcher(input);
        if (matcher.find()) {
            return matcher.group(0);
        }
        return null;
    }

    /**
     * 从指定地址获取ip
     *
     * @param targetUrl
     * @return
     */
    static public String getResource(String targetUrl) {
        HttpGet httpReq = new HttpGet(targetUrl);
        httpReq.setConfig(reqConfig);
        try {
            // 执行请求
            CloseableHttpResponse httpResp = httpClient.execute(httpReq);
            HttpEntity entity = httpResp.getEntity();
            if (entity != null) {
                String result = EntityUtils.toString(entity, "utf-8");
                logger.warn("getProxys from {}", targetUrl);
                return result;
            }
            // 获取http code
            httpResp.close();
            httpReq.abort();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
